//Copyright (C)2002 Merkur ( merkur-@users.sourceforge.net / http://www.emule-project.net )
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either
//version 2 of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

#ifndef PARTFILE_H
#define PARTFILE_H

#include "wintypes.h"
#include "KnownFile.h"
#include "types.h"
#include "opcodes.h"
#include "BarShader.h"
#include "ED2KLink.h"
#include "wx/dc.h"
#include "wx/dcmemory.h"
#include "wx/treectrl.h"

#define	PS_READY			0
#define	PS_EMPTY			1
#define PS_WAITINGFORHASH	2
#define PS_HASHING			3
#define PS_ERROR			4
#define	PS_UNKNOWN			6
#define PS_PAUSED			7
#define PS_COMPLETING		8
#define PS_COMPLETE			9

#define PR_VERYLOW			4 // I Had to change this because it didn't save negative number correctly.. Had to modify the sort function for this change..
#define PR_LOW				0 //*
#define PR_NORMAL			1 // Don't change this - needed for edonkey clients and server!
#define	PR_HIGH				2 //*
#define PR_VERYHIGH			3
#define PR_AUTO				5 //UAP Hunter
#define SRV_PR_LOW			2
#define SRV_PR_NORMAL		0
#define SRV_PR_HIGH			1

//#define BUFFER_SIZE_LIMIT	500000 // Max bytes before forcing a flush
#define BUFFER_TIME_LIMIT	5000   // Max milliseconds before forcing a flush

class CSearchFile;
class CUpDownClient;

struct PartFileBufferedData
{
	BYTE *data;						// Barry - This is the data to be written
	uint32 start;					// Barry - This is the start offset of the data
	uint32 end;						// Barry - This is the end offset of the data
	Requested_Block_Struct *block;	// Barry - This is the requested block that this data relates to
};

class CPartFile : public CKnownFile {
public:
	CPartFile();
	CPartFile(CSearchFile* searchresult);  //used when downloading a new file
	CPartFile(CString edonkeylink);
	CPartFile(class CED2KFileLink* fileLink);
	void InitializeFromLink(CED2KFileLink* fileLink);
	virtual ~CPartFile();
	
	bool	CreateFromFile(char* directory,char* filename)	{return false;}// not supported in this class
	bool	LoadFromFile(FILE* file)						{return false;}
	bool	WriteToFile(FILE* file)							{return false;}
	bool	IsPartFile()									{return !(status == PS_COMPLETE);}
	uint32	Process(uint32 reducedownload);
	bool	LoadPartFile(char* in_directory, char* filename); //filename = *.part.met
	bool	SavePartFile();
	void	PartFileHashFinished(CKnownFile* result);
	bool	HashSinglePart(uint16 partnumber); // true = ok , false = corrupted	

	void	AddGap(uint32 start, uint32 end);
	void	FillGap(uint32 start, uint32 end);
	void	DrawStatusBar(wxMemoryDC* dc, wxRect rect, bool bFlat);
	bool	IsComplete(uint32 start, uint32 end);
	bool	IsPureGap(uint32 start, uint32 end);
	bool	IsCorruptedPart(uint16 partnumber);
	void	UpdateCompletedInfos();

	bool	GetNextRequestedBlock(CUpDownClient* sender,Requested_Block_Struct** newblocks,uint16* count);
	void	WritePartStatus(CMemFile* file);
	void	AddSources(CMemFile* sources,uint32 serverip, uint16 serverport);
	uint8	GetStatus(bool ignorepause = false);
	void	NewSrcPartsInfo();
	void	SetPriority(uint8 np);
	char*	GetPartMetFileName()							{return partmetfilename;}
	uint32	GetTransfered()									{return transfered;}
	uint8	GetPriority()									{return priority;}
	char*	GetFullName()									{return fullname;}
	uint16	GetSourceCount();
	uint16	GetTransferingSrcCount()						{return transferingsrc;}
	uint32	GetDatarate()									{return datarate;}
	float	GetPercentCompleted()							{return percentcompleted;}
	uint16  GetNotCurrentSourcesCount();
	int		GetValidSourcesCount();
	bool	IsMovie();
	bool	IsArchive(); // Barry - Also want to preview archives
	CString CPartFile::getPartfileStatus(); //<<--9/21/02
	sint32	CPartFile::getTimeRemaining(); //<<--9/21/02
	time_t	lastseencomplete;
	int		getPartfileStatusRang();
        CString GetDownloadFileInfo();

	// Barry - Added as replacement for BlockReceived to buffer data before writing to disk
	uint32	WriteToBuffer(uint32 transize, BYTE *data, uint32 start, uint32 end, Requested_Block_Struct *block);
	void	FlushBuffer(void);
	// Barry - This will invert the gap list, up to caller to delete gaps when done
	// 'Gaps' returned are really the filled areas, and guaranteed to be in order
	void	GetFilledList(CTypedPtrList<CPtrList, Gap_Struct*> *filled);

	// Barry - Is archive recovery in progress
	volatile bool m_bRecoveringArchive;

	// Barry - Added to prevent list containing deleted blocks on shutdown
	void	RemoveAllRequestedBlocks(void);

	void	RemoveBlockFromList(uint32 start,uint32 end);
	void	RemoveAllSources(bool bTryToSwap);
	void	DeleteFile();
	void	StopFile();
	void	PauseFile();
	void	ResumeFile();

	virtual	Packet* CreateSrcInfoPacket(CUpDownClient* forClient);
	void	AddClientSources(CMemFile* sources);

	void	PreviewFile();
	bool	PreviewAvailable();
	uint8   GetAvailablePartCount()			{return availablePartsCount;}
	void	UpdateAvailablePartsCount();

	uint32	GetLastAnsweredTime()			{ return m_ClientSrcAnswered; }
	void	SetLastAnsweredTime()			{ m_ClientSrcAnswered = ::GetTickCount(); }
	void	SetLastAnsweredTimeTimeout()	{ m_ClientSrcAnswered = 2 * CONNECTION_LATENCY +
											                        ::GetTickCount() - SOURCECLIENTREASK; }
	uint64	GetLostDueToCorruption()		{return m_iLostDueToCorruption;}
	uint64	GetGainDueToCompression()		{return m_iGainDueToCompression;}
	uint32	TotalPacketsSavedDueToICH()		{return m_iTotalPacketsSavedDueToICH;}
	bool	HasComment()					{return hasComment;}
	bool	HasRating()						{return hasRating;}
	bool	HasBadRating();
	void	SetHasComment(bool in)			{hasComment=in;}
	void	SetHasRating(bool in)			{hasRating=in;}
	void	UpdateFileRatingCommentAvail();

        wxString GetProgressString(uint16 size);

	int		GetCommonFilePenalty();
	void	UpdateDisplayedInfo(bool force=false);
	time_t	GetLastChangeDatetime(bool forcecheck=false);
	uint8	GetCategory();
	void	SetCategory(uint8 cat)			{m_category=cat;SavePartFile();}

	CFile	m_hpartfile;	//permanent opened handle to avoid write conflicts
	volatile bool m_bPreviewing;
	//UAP Hunter
	void    UpdateUploadAutoPriority(void) ;
	bool	IsAutoPrioritized() { return m_bAutoPriority ; }
	void	SetAutoPriority(bool newAutoPriority) { this->m_bAutoPriority = newAutoPriority ; }
	//end UAP
protected:
	bool	GetNextEmptyBlockInPart(uint16 partnumber,Requested_Block_Struct* result);
	bool	IsAlreadyRequested(uint32 start, uint32 end);
	void	CompleteFile(bool hashingdone);
	void	CreatePartFile();
	void	Init();
	wxMutex 	m_FileCompleteMutex; // Lord KiRon - Mutex for file completion
private:
	uint16	count;
	uint16	transferingsrc;
	uint32  completedsize;
	uint64	m_iLostDueToCorruption;
	uint64	m_iGainDueToCompression;
	uint32  m_iTotalPacketsSavedDueToICH; 
	uint32	datarate;
	char*	fullname;
	char*	partmetfilename;
	uint32	transfered;
	bool	paused;
	uint8	priority;
	uint8	status;
	bool	newdate;	// indicates if there was a writeaccess to the .part file
	uint32	lastsearchtime;
	uint32	lastpurgetime;
	uint32	m_LastNoNeededCheck;
	CTypedPtrList<CPtrList, Gap_Struct*> gaplist;
	CTypedPtrList<CPtrList, Requested_Block_Struct*> requestedblocks_list;
	CArray<uint16,uint16> m_SrcpartFrequency;
	float	percentcompleted;
	CList<uint16,uint16>	corrupted_list;
	uint8	availablePartsCount;
	uint32	m_ClientSrcAnswered;
	uint32	m_nSavedReduceDownload;
	bool	m_bPercentUpdated;
	static	CBarShader s_LoadBar; 
	static	CBarShader s_ChunkBar; 
    bool	m_bAutoPriority ;	//UAP Hunter
	bool	hasRating;
	bool	hasComment;
	BOOL 	PerformFileComplete(); // Lord KiRon
	static UINT CompleteThreadProc(CPartFile* pFile); // Lord KiRon - Used as separate thread to complete file
	void    CharFillRange(wxString* buffer,float start, float end, char color);

	DWORD	m_lastRefreshedDLDisplay;
	DWORD   m_lastdatetimecheck;
	time_t	m_lastdatecheckvalue;

	// Barry - Buffered data to be written
	CTypedPtrList<CPtrList, PartFileBufferedData*> m_BufferedData_list;
	uint32 m_nTotalBufferData;
	uint32 m_nLastBufferFlushTime;
	uint8	m_category;

public:
	CTypedPtrList<CPtrList, CUpDownClient*> srclists[SOURCESSLOTS];
	bool	srcarevisible; // used for downloadlistctrl
	bool	hashsetneeded;
	uint32  GetCompletedSize()   {return completedsize;}
};


#endif
